"""
验证签名header
"""
import copy
import hashlib
import datetime
import requests

from urllib.parse import urlsplit, quote
from loguru import logger

from minio.signer import sign_v4_s3
from minio.credentials import Credentials
from fastapi.requests import Request
from requests_aws4auth import AWS4Auth

from data.global_var import REGION, ACCESS_KEY, SECRET_KEY, SERVICE

# 模拟 S3 的认证信息
credentials = Credentials(ACCESS_KEY, SECRET_KEY)
aws4auth = AWS4Auth(ACCESS_KEY, SECRET_KEY, REGION, SERVICE)


# 验证签名header
async def verify_signature_back(request: Request):
    # 获取请求头
    received_headers = request.headers
    # 获取签名日期 时间戳
    received_date_timestamp = received_headers.get("X-Amz-Date")
    # 获取授权头
    received_authorization = received_headers.get("Authorization")
    # 解析授权头
    if not received_authorization:
        logger.error("没有 Authorization 头")
        return False
    # 提取访问密钥和签名
    received_access_key = None
    received_signature = None
    parts = received_authorization.split(",")
    for part in parts:
        if "Credential=" in part:
            credential_part = part.split("Credential=")[1]
            received_access_key = credential_part.split('/')[0]
        elif "Signature=" in part:
            received_signature = part.split("Signature=")[1]
    if not received_access_key or received_access_key != credentials.access_key:
        logger.error(f"密钥不正确. 期望: {credentials.access_key}, 但是收到: {received_access_key}")
        return False
    if not received_signature:
        logger.error("在收到的 Authorization 头中没有 Signature 字段")
        return False

    # 获取请求体
    received_body = await request.body()
    # 剔除请求头中的签名部分
    headers_to_sign = copy.deepcopy(dict(received_headers.items()))
    if "Authorization" in headers_to_sign:
        del headers_to_sign["Authorization"]
    elif "authorization" in headers_to_sign:
        del headers_to_sign["authorization"]
    if 'accept-encoding' in headers_to_sign:
        del headers_to_sign['accept-encoding']
    elif 'Accept-Encoding' in headers_to_sign:
        del headers_to_sign['Accept-Encoding']
    if received_body == b'':
        if 'content-length' in headers_to_sign:
            del headers_to_sign['content-length']
        elif 'Content-Length' in headers_to_sign:
            del headers_to_sign['Content-Length']

    calculation_content_sha256 = hashlib.sha256(received_body).hexdigest()

    received_content_sha256 = headers_to_sign['x-amz-content-sha256']
    if received_content_sha256 != calculation_content_sha256:
        logger.error(f"请求体 sha256 值不正确. 期望: {received_content_sha256}, 但是收到: {calculation_content_sha256}")
        return False

    received_method = request.method
    # 把url中的
    received_url = urlsplit(str(request.url))
    # 对路径部分进行编码  防止出现\
    encoded_path = quote(received_url.path)
    # 将编码后的路径重新组合成完整的 URL
    received_url = received_url._replace(path=encoded_path)
    region = REGION

    # 把20250414T001911Z转换成datetime格式
    date = datetime.datetime.strptime(received_date_timestamp, '%Y%m%dT%H%M%SZ')  # 2025-04-14 00:29:50.294189+00:00
    calculation_signature_headers = sign_v4_s3(received_method,
                                               received_url,
                                               region,
                                               headers_to_sign,
                                               credentials,
                                               calculation_content_sha256,
                                               date)
    calculation_authorization = calculation_signature_headers['Authorization']
    calculation__signature = ''
    parts = calculation_authorization.split(",")
    for part in parts:
        if "Signature=" in part:
            calculation__signature = part.split("Signature=")[1]
    if calculation__signature == received_signature:
        # logger.info(f"签名验证成功")
        return True
    else:
        logger.info(f'收到的请求头: {received_headers}')
        logger.info(f'收到的签名日期: {received_date_timestamp}')
        logger.info(f'收到的授权头: {received_authorization}')
        logger.info(f"收到的密钥: {received_access_key}")
        logger.info(f"收到的签名: {received_signature}")
        logger.info(f"计算得到的请求提的 sha256 值: {calculation_content_sha256}")
        logger.info(f"使用得到的下面的请求参数计算签名:")
        print('--------------:data:', received_body)
        print("--------------method:", received_method)
        print("--------------url:", received_url)
        print("--------------region:", region)
        print("--------------headers:", headers_to_sign)
        print("--------------content_sha256:", received_content_sha256)
        print("--------------date:", received_date_timestamp)
        logger.info(f"计算的签名: {calculation__signature}")
        logger.info(f"计算出的签名: {calculation__signature}\n和收到的签名: {received_signature}\n不相符")
        return False


# 使用requests_aws4auth库验证签名header
async def verify_signature(request: Request, body: bytes = b''):
    # 获取请求头
    method = request.method
    url = str(request.url)
    headers = dict(request.headers)
    # 获取授权头
    received_authorization = headers.get("Authorization", headers.get("authorization", None))
    # 解析授权头
    if not received_authorization:
        logger.error("没有 Authorization 头")
        return False
    # 提取访问密钥和签名
    received_access_key = None
    received_signature = None
    parts = received_authorization.split(",")
    for part in parts:
        if "Credential=" in part:
            credential_part = part.split("Credential=")[1]
            received_access_key = credential_part.split('/')[0]
        elif "Signature=" in part:
            received_signature = part.split("Signature=")[1]
    if not received_access_key or received_access_key != credentials.access_key:
        logger.error(f"密钥不正确. 期望: {credentials.access_key}, 但是收到: {received_access_key}")
        return False
    if not received_signature:
        logger.error("在收到的 Authorization 头中没有 Signature 字段")
        return False

    request = requests.Request(method=method, url=url, headers=headers, data=body)
    # 不发送请求 只是得到签名后的headers
    prepared_request = request.prepare()
    calculation_result = aws4auth(prepared_request)
    calculation_authorization = calculation_result.headers['Authorization']
    calculation__signature = ''
    parts = calculation_authorization.split(",")
    for part in parts:
        if "Signature=" in part:
            calculation__signature = part.split("Signature=")[1]
    return calculation__signature == received_signature

